/* 
 * 用于段描述符的一些宏定义
 */ 
#define MMU_FULLACCESS (3<<10)      /* 访问权限 */
#define MMU_DOMAIN (0<<5)           /* 属于哪个域 */
#define MMU_SPECIAL (1<<4)          /* 必须是1 */
#define MMU_CACHEABLE (1<<3)        /* cacheable */
#define MMU_BUFFERABLE (1<<2)       /* bufferable */
#define MMU_SECTION (2<<0)          /* 段描述符 */

#define SECDESC (MMU_SECTION | MMU_SPECIAL | MMU_DOMAIN | MMU_FULLACCESS)
#define SECDESC_WB (MMU_SECTION | MMU_SPECIAL | MMU_DOMAIN | MMU_FULLACCESS\
                    | MMU_BUFFERABLE | MMU_CACHEABLE)

void create_page_table(void)
{
    unsigned long *ttb = (unsigned long *)0x30000000;
    unsigned long vaddr = 0xA0000000;
    unsigned long paddr = 0x56000000;
    
    *(ttb + (vaddr>>20)) = (paddr & 0xfff00000) | SECDESC;

    vaddr = 0x30000000;
    paddr = 0x30000000;

    while(vaddr < 0x34000000) {
        *(ttb + (vaddr>>20)) = (paddr & 0xfff00000) | SECDESC_WB;
        vaddr += 0x100000;
        paddr += 0x100000;
    }
}

void mmu_enable()
{
    __asm__(
        //写入ttb
        "ldr r0, =0x30000000\n"         
        "mcr p15,0,r0,c2,c0,0\n"
        
        //不检查访问权限
        "mvn r0, #0x0\n"                
        "mcr p15,0,r0,c3,c0,0\n"

        //使能mmu
        "mrc p15,0,r0,c1,c0,0\n"        
        "orr r0, r0, #0x01\n"
        "mcr p15,0,r0,c1,c0,0\n"
        :
        :
           );
}

void mmu_init()
{
    create_page_table();
    mmu_enable();
}
